/*
 * Brian M. Luger
 * Date: 11/20/2011
 * Conference Object
 */

package caobject;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * @author Brian M. Luger
 * @version 11/20/2011
 * 
 * Conference Class
 */
public class Conference implements Serializable 
{
	/**
	 * Generated SV-UID
	 */
	private static final long serialVersionUID = -7258277371877328659L;

	/**
	 * Author User Type Index.
	 */
	public static final int AUTHOR = 0;
	
	/**
	 * Reviewer User Type Index
	 */
	public static final int REVIEWER = 1;
	
	/**
	 * Conference Title.
	 */
	private String my_confTitle;
	
	/**
	 * A List of User Objects.
	 */
	private final Set<User> my_users;
	
	/**
	 * A List of Manuscript Objects.
	 */
	private final Set<Manuscript> my_manuscripts;
	
	/**
	 * Conference Deadlines.
	 */
	private final GregorianCalendar[] my_deadlines;
	
	/**
	 * Conference Constructor.
	 */
	public Conference(final User thePC,
			final String the_confTitle) {
		my_confTitle = the_confTitle;
		my_users = new HashSet<User>();
		my_manuscripts = new HashSet<Manuscript>();
		my_deadlines = new GregorianCalendar[2];
		
		my_users.add(thePC);
	}
	
	/**
	 * Method used to add a Manuscript to the Conference.
	 * 
	 * </br></br>
	 * 
	 * <b><i>Pre</i></b>: Manuscript must not already be
	 * in the set of manuscripts.
	 * </br>
	 * <b><i>Post</i></b>: Manuscript is added to the list
	 * of manuscripts.
	 * 
	 * @param theManuscript The Manuscript to be added to
	 * the Conference.
	 */
	public void addManuscript(final 
			Manuscript theManuscript) {
		my_manuscripts.add(theManuscript);
	}
	
	/**
	 * This method replaces a manuscript in the Set of 
	 * Manuscripts with a new one.
	 * 
	 * </br></br>
	 * 
	 * <b><i>Pre</i></b>: <tt>theOldManuscript</tt> must be
	 * a Manuscript in the Set of Manuscripts. And 
	 * <tt>theNewManuscript</tt> must not be null.
	 * </br>
	 * <b><i>Post</i></b>: <tt>theOldManuscript</tt> is 
	 * replaced with <tt>theNewManuscript</tt>.
	 * 
	 * @param theOldManuscript The Manuscript to be 
	 * replaced.
	 * @param theNewManuscript The new Manuscript.
	 */
	public void replaceManuscript(final Manuscript 
			theOldManuscript, final Manuscript 
			theNewManuscript) {
		
		my_manuscripts.remove(theOldManuscript);
		my_manuscripts.add(theNewManuscript);
		
	}
	
	/**
	 * Method used to retrieve all of the Manuscripts 
	 * associated with the Conference.
	 * 
	 * @return The Set of Manuscripts associated with the
	 * Conference.
	 */
	public Set<Manuscript> getManuscripts() {
		return my_manuscripts;
	}
	
	/**
	 * Method used to retrieve Manuscripts associated with a
	 * given user.
	 * 
	 * </br></br>
	 * 
	 * <b><i>Pre</i></b>: <tt>anAuthor</tt> must NOT be
	 * <tt>null</tt>
	 * </br>
	 * <b><i>Post</i></b>: All Manuscripts authored by
	 * <tt>anAuthor</tt> will be retrieved.
	 * 
	 * @param anAuthor The Author of the Manuscripts being
	 * retrieved.
	 * 
	 * @return An <tt>ArrayList</tt> of Manuscripts 
	 * authored by <tt>anAuthor</tt>.
	 */
	public ArrayList<Manuscript> getManuscripts(
			final String anAuthor) {
		final Manuscript[] manuscriptList = 
			my_manuscripts.toArray(new Manuscript[0]);
		
		final ArrayList<Manuscript> authorManuscriptList = 
			new ArrayList<Manuscript>();
		
		for (Manuscript m : manuscriptList){
			if (m.getAuthor().equalsIgnoreCase(anAuthor)) {
				authorManuscriptList.add(m);
			}
		}
		
		return authorManuscriptList;
	}
	
	/**
	 * Method used to retrieve a single Manuscript 
	 * associated with a given Manuscript Title.
	 * 
	 * </br></br>
	 * 
	 * <b><i>Pre</i></b>: <tt>anAuthor</tt> and 
	 * <tt>aTitle</tt> must NOT be null.
	 * 
	 * </br>
	 * <b><i>Post</i></b>: The Manuscript authored by
	 * <tt>anAuthor</tt> and titled <tt>aTitle</tt> will 
	 * be retrieved.
	 * 
	 * @param anAuthor The Author of the paper to be 
	 * retrieved.
	 * @param aTitle The title of the paper to be retrieved.
	 *
	 * @return The <tt>Manuscript</tt>.
	 */
	public Manuscript getAManuscript(final String anAuthor,
			final String aTitle){
		int manuscriptIndex = 0;
		
		final Manuscript[] manuscriptList = 
			my_manuscripts.toArray(new Manuscript[0]);
		
		for (int i = 0; i < manuscriptList.length; i++) {
			if (manuscriptList[i].getAuthor().
					equalsIgnoreCase(anAuthor) 
					&& manuscriptList[i].getTitle().
					equalsIgnoreCase(aTitle)) {
				manuscriptIndex = i;
				break;
			}
		}
		
		return manuscriptList[manuscriptIndex];
	}
	
	/**
	 * Method for adding a user to our Set of Users.
	 * </br></br>
	 * <b><i>Pre</i></b>: <tt>the_user</tt> must not be
	 * null.
	 * </br>
	 * <b><i>Post</i></b>: <tt>the_user</tt> is added to 
	 * the <tt>Set</tt> of Users.
	 * 
	 * @param the_user User to be added.
	 **/
	public void addUser(final User the_user) {
		
		my_users.add(the_user);
	}
	
	/**
	 * Method used to retrieve a User.
	 * 
	 * @param aUserName Name of the user you are 
	 * retrieving, represented as a String.
	 * 
	 * @return A <tt>User</tt> with name <tt>aUserName</tt>
	 * or null if <tt>User</tt> does not exist in the Set.
	 */
	public User getUser(final String aUserName) {
		
		User theUser = null;
		
		for (User u : my_users) {
			if (u.getUserName().
					equalsIgnoreCase(aUserName)) {
				theUser = u;
			}
		}
		
		return theUser;
	}
	
	/**
	 * @return Set of Users participating in the Conference.
	 */
	public Set<User> getUsers() {
		return my_users;
	}
	
	/**
	 * Method used to set the deadline for a particular
	 * user type.
	 * </br></br>
	 * <b><i>Pre</i></b>: <tt>the_userType</tt> must be
	 * <tt>Conference.AUTHOR</tt> <b>OR</b> 
	 * <tt>Conference.REVEWER</tt>.
	 * </br>
	 * <b><i>Post</i></b>: Deadline is set for the 
	 * appropriate User Type.
	 * 
	 * @param the_user The User wanting to set the 
	 * deadline.
	 * @param the_userType The User Type (Author/Reviewer).
	 * @param the_deadline The Deadline.
	 * 
	 * @return <tt>true</tt> if deadline was set 
	 * successfully, <tt>false</tt> otherwise.
	 */
	public void setDeadline(final int the_userType,
			final GregorianCalendar the_deadline) {
			
		my_deadlines[the_userType] = the_deadline;
	}
	
	/**
	 * Method used to retrieve the deadline for the 
	 * specified user type.
	 * </br></br>
	 * <b><i>Pre</i></b>: <tt>the_userType</tt> must be
	 * <tt>Conference.AUTHOR</tt> <b>OR</b> 
	 * <tt>Conference.REVEWER</tt>.
	 * </br>
	 * <b><i>Post</i></b>: Deadline is returned for the
	 * <tt>the_userType</tt>.
	 * 
	 * @param the_userType The User Type (Author/Reviewer)
	 * 
	 * @return The deadline.
	 */
	public GregorianCalendar getDeadline(
			final int the_userType) {
		return my_deadlines[the_userType];
	}
	
	/**
	 * @return The title of the conference.
	 */
	public String getTitle() {
		return my_confTitle;
	}
}
